package vpn

import (
	"encoding/json"
	"fmt"
	"gitee.com/cdsailyj/go-vpn/common/tool"
	"github.com/gorilla/websocket"
	"github.com/pion/webrtc/v3"
	"golang.org/x/net/context"
	"log"
	"net/url"
	"sync"
	"time"
)

type SignalingClient struct {
	conn           *websocket.Conn
	PeerConnection *webrtc.PeerConnection
	DataChannel    *webrtc.DataChannel
	clientID       string
	targetID       string
	isMaster       bool
	PeerConnected  bool
	mutex          sync.Mutex // 添加互斥锁
	ctx            context.Context
	cancel         context.CancelFunc
}

func NewSignalingClient(serverURL, clientID, targetID string, isMaster bool) (*SignalingClient, error) {

	u := url.URL{
		Scheme:   "ws",
		Host:     serverURL,
		Path:     "/ws",
		RawQuery: "client=" + clientID,
	}

	dialer := tool.GetWebsocketDialer(serverURL)
	conn, _, err := dialer.Dial(u.String(), nil)
	if err != nil {
		return nil, err
	}

	// 监听信令消息

	s := &SignalingClient{
		conn:     conn,
		clientID: clientID,
		targetID: targetID,
		isMaster: isMaster,
	}

	go s.readMessages()

	return s, nil
}

// 创建数据通道
func (s *SignalingClient) CreateDataChannel() (*webrtc.DataChannel, error) {
	dataChannel, err := s.PeerConnection.CreateDataChannel("control", &webrtc.DataChannelInit{
		Ordered:           &[]bool{true}[0],
		MaxPacketLifeTime: &[]uint16{1000}[0], // 1秒
	})
	if err != nil {
		return nil, err
	}
	fmt.Println("✅ 数据通道创建成功")
	dataChannel.OnOpen(func() {
		fmt.Println("📡 数据通道已打开")
	})
	s.DataChannel = dataChannel
	return dataChannel, nil
}

func (s *SignalingClient) SetPeerConnection() error {
	ctx, cancel := context.WithCancel(context.Background())
	s.cancel = cancel
	s.ctx = ctx

	// 创建 PeerConnection
	config := webrtc.Configuration{
		ICEServers: []webrtc.ICEServer{
			{URLs: []string{"stun:stun.qq.com:3478"}},
		},
	}

	peerConnection, err := webrtc.NewPeerConnection(config)
	if err != nil {
		return err
	}

	// 设置视频轨道处理
	peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
		fmt.Printf("🎥 接收到视频轨道: %s, 编码: %s\n", track.ID(), track.Codec().MimeType)
	})

	// 设置数据通道处理
	peerConnection.OnDataChannel(func(dc *webrtc.DataChannel) {
		fmt.Printf("📡 接收到数据通道: %s\n", dc.Label())

		s.DataChannel = dc
		dc.OnMessage(func(msg webrtc.DataChannelMessage) {
			fmt.Printf("收到数据通道的消息: %#v \n", string(msg.Data))
		})

		dc.OnOpen(func() {
			fmt.Println("📡 数据通道已打开")
		})
	})

	// 处理 ICE candidate
	peerConnection.OnICECandidate(func(candidate *webrtc.ICECandidate) {
		if candidate != nil {
			s.SendMessage(Message{
				Type: "ice",
				Data: candidate.ToJSON(),
				From: s.clientID, // 添加From字段
				To:   s.targetID,
			})
		}
	})

	// 添加连接状态监控
	s.PeerConnected = false
	peerConnection.OnConnectionStateChange(func(state webrtc.PeerConnectionState) {
		fmt.Printf("🔗 WebRTC连接状态: %s\n", state.String())
		switch state {
		case webrtc.PeerConnectionStateConnected:
			s.PeerConnected = true
			fmt.Println("✅ WebRTC连接已建立!")
		case webrtc.PeerConnectionStateDisconnected, webrtc.PeerConnectionStateFailed:
			s.PeerConnected = false
			fmt.Println("❌ WebRTC连接断开")
		}
	})

	// 定期重发offer直到连接建立
	go func() {
		ticker := time.NewTicker(5 * time.Second) // 每5秒重发一次
		defer ticker.Stop()

		for {
			select {
			case <-s.ctx.Done():
				fmt.Println("定期重发offer直到连接建立 停止")
				return
			case <-ticker.C:
				if !s.PeerConnected && s.isMaster {
					fmt.Printf("🔄 连接未建立，需要重发offer...当前状态: %s\n", peerConnection.ConnectionState().String())
				}
			}
		}
	}()

	peerConnection.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
		fmt.Printf("❄️ ICE连接状态: %s\n", state.String())
	})

	s.PeerConnection = peerConnection

	return nil
}

func (s *SignalingClient) Close() {
	s.cancel()
	s.conn.Close()
	s.PeerConnection.Close()
}

func (s *SignalingClient) readMessages() {
	for {
		var msg Message
		err := s.conn.ReadJSON(&msg)
		if err != nil {
			log.Printf("Read message error: %v", err)
			return
		}

		s.handleSignalingMessage(msg)
	}
}

func (s *SignalingClient) handleSignalingMessage(msg Message) {
	fmt.Printf("📨 收到信令消息: 类型=%s, 来自=%s, 目标=%s\n", msg.Type, msg.From, msg.To)

	switch msg.Type {
	case "offer":
		// B电脑收到A电脑的offer
		fmt.Println("🔄 B电脑处理offer...")

		// 解析offer
		offerData, err := json.Marshal(msg.Data)
		if err != nil {
			log.Printf("❌ 序列化offer数据失败: %v", err)
			return
		}

		offer := webrtc.SessionDescription{}
		if err := json.Unmarshal(offerData, &offer); err != nil {
			log.Printf("❌ 解析offer失败: %v", err)
			return
		}

		// 设置远程描述
		if err := s.PeerConnection.SetRemoteDescription(offer); err != nil {
			log.Printf("❌ 设置远程描述失败: %v", err)
			return
		}

		// 创建answer
		answer, err := s.PeerConnection.CreateAnswer(nil)
		if err != nil {
			log.Printf("❌ 创建answer失败: %v", err)
			return
		}

		// 设置本地描述
		if err := s.PeerConnection.SetLocalDescription(answer); err != nil {
			log.Printf("❌ 设置本地描述失败: %v", err)
			return
		}

		// 发送answer
		if err := s.SendMessage(Message{
			Type: "answer",
			Data: answer,
			From: s.clientID, // B电脑的ID
			To:   msg.From,   // 发给A电脑
		}); err != nil {
			log.Printf("❌ 发送answer失败: %v", err)
			return
		}

		fmt.Println("✅ B电脑已发送answer")

	case "answer":
		// A电脑收到B电脑的answer
		fmt.Println("🔄 A电脑处理answer...")

		answerData, err := json.Marshal(msg.Data)
		if err != nil {
			log.Printf("❌ 序列化answer数据失败: %v", err)
			return
		}

		answer := webrtc.SessionDescription{}
		if err := json.Unmarshal(answerData, &answer); err != nil {
			log.Printf("❌ 解析answer失败: %v", err)
			return
		}

		if err := s.PeerConnection.SetRemoteDescription(answer); err != nil {
			log.Printf("❌ 设置远程描述失败: %v", err)
			return
		}

		fmt.Println("✅ A电脑已处理answer")

	case "ice":
		// 处理ICE candidate
		candidateData, err := json.Marshal(msg.Data)
		if err != nil {
			log.Printf("❌ 序列化ICE数据失败: %v", err)
			return
		}

		candidate := webrtc.ICECandidateInit{}
		if err := json.Unmarshal(candidateData, &candidate); err != nil {
			log.Printf("❌ 解析ICE candidate失败: %v", err)
			return
		}

		if err := s.PeerConnection.AddICECandidate(candidate); err != nil {
			log.Printf("❌ 添加ICE candidate失败: %v", err)
			return
		}

		fmt.Printf("✅ 添加ICE candidate: %s\n", candidate.Candidate)
	case "ready":
		if s.PeerConnection != nil {
			s.PeerConnection.Close()
			s.cancel()
		}

		// 启动信令
		if err := s.SetPeerConnection(); err != nil {
			log.Printf("❌ 启动 ready 信令失败:%v\n", err)
			return
		}

		fmt.Printf("✅ 启动 ready 信令成功: %v\n", msg)
	}

}

func (s *SignalingClient) SendMessage(msg Message) error {
	// 加锁保护WebSocket写入
	s.mutex.Lock()
	defer s.mutex.Unlock()

	// 确保每条消息都有From字段
	if msg.From == "" {
		msg.From = s.clientID
	}

	fmt.Printf("📤 发送信令消息: 类型=%s, 来自=%s, 目标=%s\n", msg.Type, msg.From, msg.To)
	return s.conn.WriteJSON(msg)
}

// A电脑创建并发送offer
// A电脑创建并发送offer
func (s *SignalingClient) CreateAndSendOffer() error {
	// 检查当前状态，避免重复设置
	currentState := s.PeerConnection.SignalingState()
	if currentState == webrtc.SignalingStateHaveLocalOffer {
		fmt.Printf("⏸️ 已有本地offer，跳过创建。当前信令状态: %s\n", currentState)
		return nil
	}

	// 如果处于稳定状态或没有远程描述，可以创建新offer
	if currentState != webrtc.SignalingStateStable && currentState != webrtc.SignalingStateHaveRemoteOffer {
		fmt.Printf("⚠️ 当前信令状态 %s 不适合创建offer\n", currentState)
		return nil
	}

	offer, err := s.PeerConnection.CreateOffer(nil)
	if err != nil {
		return err
	}

	err = s.PeerConnection.SetLocalDescription(offer)
	if err != nil {
		return err
	}

	return s.SendMessage(Message{
		Type: "offer",
		Data: offer,
		From: s.clientID,
		To:   s.targetID,
	})
}
